#include <locale.h>
#include <sys/time.h>
#include <unistd.h>

#include <clocale>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <string>

class WTimer {
 private:
  struct timespec ts_begin_{}, ts_end_{};

 public:
  WTimer();
  ~WTimer() = default;

  void 开始();
  void 结束();
  long long int get_elapsed_time_in_nanosec() const;

  std::wstring to_wstring();
};

WTimer::WTimer::WTimer() { 开始(); }

void WTimer::开始() { clock_gettime(CLOCK_MONOTONIC, &ts_begin_); }

void WTimer::结束() { clock_gettime(CLOCK_MONOTONIC, &ts_end_); }

long long int WTimer::get_elapsed_time_in_nanosec() const {
  struct timespec ts;

  ts.tv_sec = ts_end_.tv_sec - ts_begin_.tv_sec;
  ts.tv_nsec = ts_end_.tv_nsec - ts_begin_.tv_nsec;

  return ts.tv_sec * 1000000000 + ts.tv_nsec;
}

std::wstring WTimer::to_wstring() {
  struct timespec ts;

  ts.tv_sec = ts_end_.tv_sec - ts_begin_.tv_sec;
  ts.tv_nsec = ts_end_.tv_nsec - ts_begin_.tv_nsec;

  if (ts.tv_nsec < 0) {
    --ts.tv_sec;
    ts.tv_nsec += 1000000000;  // 10 亿纳秒
  }
  wchar_t buffer[128];
  swprintf(buffer, std::size(buffer), L"耗时 %lld 秒，%lld 纳秒。", ts.tv_sec,
           ts.tv_nsec);

  return buffer;
}

/**
 * In this homework, you'll measure the costs of a system call. Measuring the
 * cost of a system call is relatively easy. For example, you could repeatedly
 * call a simple system call(e.g., performing a 0-byte read), and time how long
 * it takes; dividing the time bgy the number of iterations gives you an
 * estimate of the cost of a system call. 根据 gettimeofday
 * 的手册，这个函数已经过时 了，应该使用 clock_gettime 函数。看了一下文档，发现
 * clock_gettime 使用 CLOCK_REALTIME 时，和 gettimeofday 相同，都是计算相对于
 * Epoch 的时间。也要看看其它类型的 CLOCK。 2025年4月29日星期二 23:01
 */

static void measure_sys_call_cost(long long int count) {
  // 使用 gettimeofday，或汇编指令 rdtsc。

  WTimer timer;
  timer.开始();

  long long int temp{count};
  while (--count >= 0) {
    read(0, nullptr, 0);
  }

  timer.结束();
  wprintf(L"%ls\n单次耗时：%lld 纳秒。\n", timer.to_wstring().c_str(),
          timer.get_elapsed_time_in_nanosec() / temp);
}

int main(int argc, char* argv[], char* env[]) {
  setlocale(LC_ALL, "");

  wprintf(L"%ls\n", L"中国");
  measure_sys_call_cost(10);
  measure_sys_call_cost(100);
  measure_sys_call_cost(1000);
  measure_sys_call_cost(10000);
  measure_sys_call_cost(100000);

  return 0;
}
